package boardgamer.yavalath.client.animation;

import android.graphics.Canvas;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.Pair;
import boardgamer.common.client.animation.Animation;
import boardgamer.common.net.PlayerId;
import boardgamer.yavalath.client.RenderHelper;
import boardgamer.yavalath.client.game.YavalathDrawableBoard;
import boardgamer.yavalath.client.game.YavalathDrawableTile;
import boardgamer.yavalath.client.resources.ImageHandler;
import boardgamer.yavalath.common.YavalathPlayerState;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

import static com.google.common.base.Preconditions.checkNotNull;


public class LoseAnimation extends Animation {

  private static final int UPDATE_PERIOD = 25;
  private static final float SCALE_INCREASE = 0.01f;
  private static final int ALPHA_INCREASE = -2;

  private final ImmutableSet<LoseTile> losingTiles;
  private final Paint paint;

  public LoseAnimation(Iterable<Pair<Integer, Integer>> losingTiles,
                       YavalathPlayerState.PlayerColor loserColor,
                       final YavalathDrawableBoard board) {
    super(UPDATE_PERIOD);

    this.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    this.paint.setColorFilter(
        new LightingColorFilter(
            RenderHelper.instance().getColor(loserColor), 0));
    this.paint.setAlpha(255);

    this.losingTiles = ImmutableSet.copyOf(Iterables.transform(losingTiles,
        new Function<Pair<Integer, Integer>, LoseTile>() {
          @Override
          public LoseTile apply(Pair<Integer, Integer> input) {
            YavalathDrawableTile tile = board.getTile(input.first, input.second);
            return new LoseTile(LoseAnimation.this.paint, tile.getBoundingRect());
          }
        }));
  }

  @Override
  public boolean isDead() {
    return paint.getAlpha() <= 0;
  }

  @Override
  public void draw(Canvas canvas) {
    for (LoseTile tile : losingTiles) {
      tile.draw(canvas);
    }
  }

  @Override
  protected void onPeriodic() {
    paint.setAlpha(Math.max(paint.getAlpha() + ALPHA_INCREASE, 0));
    for (LoseTile tile : losingTiles) {
      float dx = tile.boundingRect.width() * SCALE_INCREASE / 2;
      float dy = tile.boundingRect.height() * SCALE_INCREASE / 2;
      tile.boundingRect.inset(-dx, -dy);
    }
  }

  private class LoseTile {

    private final Paint paint;
    private final RectF boundingRect;

    public LoseTile(Paint paint, RectF boundingRect) {
      this.paint = checkNotNull(paint, "paint");
      this.boundingRect = new RectF(checkNotNull(boundingRect, "boundingRect"));
    }

    public void draw(Canvas canvas) {
      canvas.drawBitmap(ImageHandler.tile, null /* srcRect */, boundingRect, paint);
    }
  }
}
